package com.chagee.store.operation.server.service;


import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
import com.chagee.store.operation.common.constant.CommonConstant;
import com.chagee.store.operation.common.enums.EmailReceiverTypeEnum;
import com.chagee.store.operation.common.enums.EmailTypeEnum;
import com.chagee.store.operation.server.config.EmailConfig;
import com.chagee.store.operation.server.model.bo.EmailConfigItem;
import com.chagee.store.operation.server.model.bo.EmailContent;
import com.chagee.store.operation.server.model.bo.EmailReceiverConfigItem;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;

/**
 * 邮件发送
 * @Author : hk
 * @Date : 2024/12/24
 */

@Service
@Slf4j
@RequiredArgsConstructor
public class EmailBizService {

	@Resource
	private JavaMailSender javaMailSender;

	@Resource
	private EmailConfig emailConfig;

	/**
	 * 发送邮件类型
	 * @param type 邮件类型
	 * @param receivers 接受人
	 * @param subjectArgs 主题参数
	 * @param messageArgs 消息体参数
	 * @param attachmentFileNameArgs 附件文件名参数
	 * @param bytes 附件文件
	 */
	public void sendEmail(EmailTypeEnum type, EmailReceiverTypeEnum receiverType,List<String> receivers, Map<String, Object> subjectArgs, Map<String, Object> messageArgs, Map<String, Object> attachmentFileNameArgs, byte[] bytes) {
		EmailConfigItem configItem = emailConfig.select(type);
		EmailContent config = configItem.getContent();
		EmailContent content = new EmailContent();
		// 填充主题
		String subject = config.getSubject();
		if (MapUtil.isNotEmpty(subjectArgs) && StringUtils.isNotBlank(subject)) {
			subject = StrUtil.format(subject, subjectArgs);
		}
		content.setSubject(subject);
		// 填充消息体
		String message = builderMsg(config, receiverType, messageArgs);
		content.setMessage(message);
		// 填充文件名
		String fileName = config.getAttachmentFileName();
		if (MapUtil.isNotEmpty(attachmentFileNameArgs) && StringUtils.isNotBlank(fileName)) {
			fileName = StrUtil.format(fileName, attachmentFileNameArgs);
		}
		content.setAttachmentFileName(fileName);
		content.setSender(configItem.getSender());
		content.setAttachmentBytes(bytes);
		content.setReceivers(receivers);
		sendEmail(content);
	}

	public String builderMsg(EmailContent config, EmailReceiverTypeEnum receiverType, Map<String, Object> messageArgs) {

		String message = config.getMessage();
		switch (receiverType) {
			case CLIQUE:
				message = config.getMessageExt();
				break;
		}

		if (MapUtil.isNotEmpty(messageArgs) && StringUtils.isNotBlank(message)) {
			message = StrUtil.format(message, messageArgs);
		}

		return message;
	}

	/**
	 * 发送邮件
	 * @param content content
	 */
	public void sendEmail(EmailContent content) {
		try {
			sendEmailInner(content);
		} catch (Exception e) {
			log.error("EmailBizService_sendEmail_exception {}", JSONUtil.toJsonStr(content), e);
		}
	}


	/**
	 * 发送邮件
	 * @param content content
	 * @throws MessagingException
	 */
	private void sendEmailInner(EmailContent content) throws MessagingException {
		MimeMessage message = javaMailSender.createMimeMessage();
		MimeMessageHelper helper = new MimeMessageHelper(message, true);
		// 单个接收人
		if (StringUtils.isNotBlank(content.getReceiver())) {
			helper.setTo(content.getReceiver());
		}
		// 多个接收人
		if (!CollectionUtils.isEmpty(content.getReceivers())) {
			Set<String> receiversSet = new HashSet<>(content.getReceivers());
			if (StringUtils.isNotBlank(content.getReceiver())) {
				receiversSet.add(content.getReceiver());
			}
			String[] receiversArray = new String[receiversSet.size()];
			helper.setTo(receiversSet.toArray(receiversArray));
		}
		helper.setFrom(content.getSender());
		helper.setSubject(content.getSubject());
		helper.setText(content.getMessage());
		// 设置附件
		setAttachment(helper, content);

		javaMailSender.send(message);
	}


	/**
	 * 设置邮箱附件
	 * @param helper helper
	 * @param content content
	 */
	private void setAttachment(MimeMessageHelper helper, EmailContent content) throws MessagingException {
		// 直接使用流
		if (Objects.nonNull(content.getAttachmentBytes())) {
			helper.addAttachment(content.getAttachmentFileName(), new InputStreamSource() {
				@Override
				public InputStream getInputStream() throws IOException {
					return new ByteArrayInputStream(content.getAttachmentBytes());
				}
			});
		}

		// url 来源于网络
		if (StringUtils.isNotBlank(content.getAttachmentUrl())) {
			String url = content.getAttachmentUrl();
			helper.addAttachment(content.getAttachmentFileName(), () -> {
				URL link = new URL(url);
				return link.openStream();
			});
		}

		// file 来源于本地
		if (content.getAttachmentFile()!= null) {
			helper.addAttachment(content.getAttachmentFileName(), content.getAttachmentFile());
		}
	}

	/**
	 * 获取excel文件流
	 * @param clazz clazz
	 * @param data data
	 * @return
	 * @param <T>
	 */
	public static <T>byte[] buildExcelBytes(Class<T> clazz, List<T> data, String sheetName) {
		if (StringUtils.isBlank(sheetName)) {
			sheetName = CommonConstant.DEFAULT_SHEET_NAME;
		}
		ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
		EasyExcel.write(outputStream, clazz)
			.sheet(sheetName)
			.registerWriteHandler(new LongestMatchColumnWidthStyleStrategy())
			.doWrite(data);
		return outputStream.toByteArray();
	}

	/**
	 * 查询邮件接受人
	 * @param type 邮件类型
	 * @param receiverTypeEnum 接受人类型
	 * @return email set
	 */
	public Map<String, String> getEmailReceivers(EmailTypeEnum type, EmailReceiverTypeEnum receiverTypeEnum) {
		EmailConfigItem configItem = emailConfig.select(type);
		String receiverConfig = configItem.getReceiverConfig();
		EmailReceiverConfigItem receiver = emailConfig.getReceiver(receiverConfig);

		// 接受人
		Map<String, String> receivers = new HashMap<>();


		switch (receiverTypeEnum) {
			case SUPPLIER:
				receivers = receiver.getSupplier();
				break;
			default:
				return receivers;
		}

		return receivers;
	}

	public String getReceivers(EmailTypeEnum type, EmailReceiverTypeEnum receiverTypeEnum) {
		EmailConfigItem configItem = emailConfig.select(type);
		String receiverConfig = configItem.getReceiverConfig();
		EmailReceiverConfigItem receiver = emailConfig.getReceiver(receiverConfig);

		// 接受人
		String receivers = "";

		switch (receiverTypeEnum) {
			case CLIQUE:
				receivers = receiver.getClique();
				break;
			default:
				return receivers;
		}
		log.info("getReceivers_emails: {}", receivers);
		return receivers;
	}

}
